package sweet.helper

/** Provide reflection to Scala types. */
trait ScalaReflection extends Logger{
  
  import scala.collection.mutable
  
  type Getter = () => AnyRef
  type Setter = AnyRef => AnyRef 
  
  val unwantedMethodNames = Set[String]() ++
      (for(m <- classOf[Object].getMethods) yield m.getName) ++
      (for(m <- classOf[ScalaReflection].getMethods) yield m.getName)
  
  /** Scala getters are those public method that doesn't ends with '=$' and
   * with zero arguments. */
  lazy val getters = {
    val map = new mutable.HashMap[String, Getter]
    this.getClass.getDeclaredMethods.foreach { m =>
      val name = m.getName
      if(m.getParameterTypes.length==0 && !name.contains("$") && !unwantedMethodNames.contains(name)){
        map += Pair(name, (() => m.invoke(this, Array())))
      }
    }
    map.readOnly
  }
  /** Scala setters that are public method ends with '=$' and has exactly one parameter of
   * clz given. */
  lazy val setters = {
    val map = new mutable.HashMap[String, Setter]
    this.getClass.getDeclaredMethods.foreach { m =>
      val name = m.getName
      if(m.getParameterTypes.length==1 && name.endsWith("_$eq") && !unwantedMethodNames.contains(name)){
        //the key needs to remove the "_$eq" suffix!
        map += Pair(name.substring(0, name.length - 4), ((value: AnyRef) => m.invoke(this, Array(value))))
      }
    }
    map.readOnly
  }
}


/** A trait that provide saving and loading from a properties file using
 * reflections injections.
 */
trait FilePropsModel extends ScalaReflection with Logger {
  import java.io._
  import sweet.helper._
      
  def loadFrom(file: File){
    val props = SProperties.loadFromXML(file)
    for((name,v) <- props){
      logger.debug("Invoking "+name+" setter with value "+v)
      val setter = setters(name)
      setter(v)
    }
  }
  def saveTo(file: File){    
    val props = SProperties()
    for((name,getter) <- getters){
      logger.debug("Invoking "+name+" getter")
      val v = getter()
      logger.debug("Value "+v)
      props(name) = v.toString
    }
    props.storeToXML(file, "ToolboxProject Data Model", "UTF-8")
  }
}

